
#include <include/sdk/misc.h>
#include "typeDefense.h"

namespace skill {
    bool Recover::canUse(Game *g, const std::vector<std::string> &params) {
        if(!CoolDownSkill::canUse(g, params)) return false;

        // 使用必须是Actor
        if(!origin->hasPrefix("_Actor_")) return false;

        int cost = RecoverCost, energy;
        Entity* target;
        // 判断参数合法性
        try{
            energy = std::stoi(origin->properties["energy"]);
            if (energy < cost) return false;
            target = g->entityManager.findEntityByID(params[0]);
            if (target == nullptr) return false;
            if (target->properties["link_in"].find("|" + origin->id + "|") != std::string::npos) return true;
            if (target->id == origin->id) return true;
            return false;
        }catch(std::exception){
            return false;
        }
    }

    bool Recover::use(Game *g, const std::vector<std::string> &params) {
        if (!CoolDownSkill::use(g, params)) return false;   //这里已经将cd重置，会不会之后技能释放失败？
        int cost = RecoverCost;
        try{
            int my_max_hp = std::stoi(origin->properties["max_hp"]);
            Entity* foe = g->entityManager.findEntityByID(params[0]);
            int foe_hp = std::stoi(foe->properties["hp"]);
            foe->properties["hp"] = std::to_string(foe_hp + int(my_max_hp * RecoverMaxHPRate + EPS));
            return true;
        }catch(std::exception){
            return false;
        }
    }

    bool Shielding::canUse(Game *g, const std::vector<std::string> &params) {
        if(!CoolDownSkill::canUse(g, params)) return false;

        if(!origin->hasPrefix("_Actor_")) return false;

        Actor *originActor = dynamic_cast<Actor *>(origin);
        Point center = originActor->pos();

        try {
            int now_energy = std::stoi(origin->properties["energy"]);
            if (now_energy < ShieldingCost) return false;
            std::stoi(originActor->properties["team"]);
        }catch (std::exception) {
            return false;
        }
        std::map<std::string, Entity*> entityList = g->entityManager.entityList;

        for(auto it = entityList.begin(); it != entityList.end(); ++it)
        {
            try{
                if(!it->second->hasPrefix("_Actor_")) continue;
                Actor *targetActor = dynamic_cast<Actor *>(it->second);
                if((targetActor->pos() - center).getSquaredEuclideanLength() > ShieldingRadius) continue;
                std::stoi(targetActor->properties["team"]);
                std::stoi(targetActor->properties["attack"]);
                std::stoi(targetActor->properties["defense"]);
            }catch(std::exception){
                return false;
            }
        }
        return true;
    }

    bool Shielding::use(Game *g, const std::vector<std::string> &params) {
        if(!CoolDownSkill::use(g, params)) return false;
        try{
            int now_energy = std::stoi(origin->properties["energy"]);
            now_energy -= ShieldingCost;
            origin->properties["energy"] = std::to_string(now_energy);
            Actor *originActor = dynamic_cast<Actor *>(origin);
            Point center = originActor->pos();
            std::map<std::string, Entity*> entityList = g->entityManager.entityList;
            for(auto it = entityList.begin(); it != entityList.end(); ++it)
            {
                if(!it->second->hasPrefix("_Actor_")) continue;
                Actor *targetActor = dynamic_cast<Actor *>(it->second);
                if((targetActor->pos() - center).getSquaredEuclideanLength() > ShieldingRadius) continue;
                if (originActor->properties["team"] == targetActor->properties["team"])
                    targetActor->learnSkill(new ShieldingBuff(int(stoi(origin->properties["defense"]) * DefenseShareRate + EPS)));
                else
                    targetActor->learnSkill(new DecAttackBuff);
            }
            return true;
        }catch(std::exception){
            return false;
        }
    }
}